home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
language
/
asxsrc.arc
/
Z80MCH.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-08-25
|
9KB
|
598 lines
/* z80mch.c */
/*
* (C) Copyright 1989
* All Rights Reserved
*
* Alan R. Baldwin
* 721 Berkeley St.
* Kent, Ohio 44240
*/
#include <stdio.h>
#include <setjmp.h>
#include "asm.h"
#include "z80.h"
char imtab[3] = { 0x46, 0x56, 0x5E };
int hd64;
/*
* Process a machine op.
*/
VOID
machine(mp)
struct mne *mp;
{
register op, t1, t2;
struct expr e1, e2;
int rf, v1, v2;
op = mp->m_valu;
rf = mp->m_type;
if (!hd64 && rf>X_HD64)
rf = 0;
switch (rf) {
case S_INH1:
outab(op);
break;
case S_INH2:
outab(0xED);
outab(op);
break;
case S_RET:
if (more()) {
if (v1 = admode(CND)) {
outab(op | v1<<3);
} else {
qerr();
}
} else {
outab(0xC9);
}
break;
case S_PUSH:
if (admode(R16X)) {
outab(op+0x30);
break;
} else
if ((v1=admode(R16)) && (v1&=0xFF)!=SP) {
if (v1 != gixiy(v1)) {
outab(op+0x20);
break;
}
outab(op | v1<<4);
break;
}
aerr();
break;
case S_RST:
v1 = absexpr();
if (v1 & ~0x38) {
aerr();
v1 = 0;
}
outab(op|v1);
break;
case S_IM:
expr(&e1, 0);
abscheck(&e1);
if (e1.e_addr > 2) {
aerr();
e1.e_addr = 0;
}
outab(op);
outab(imtab[e1.e_addr]);
break;
case S_BIT:
expr(&e1, 0);
t1 = 0;
v1 = e1.e_addr;
if (v1 > 7) {
++t1;
v1 &= 0x07;
}
op |= (v1<<3);
comma();
addr(&e2);
abscheck(&e1);
if (genop(0xCB, op, &e2, 0) || t1)
aerr();
break;
case S_RL:
t1 = 0;
t2 = addr(&e2);
if (more()) {
if ((t2 != S_R8) || (e2.e_addr != A))
++t1;
comma();
t2 = addr(&e2);
}
if (genop(0xCB, op, &e2, 0) || t1)
aerr();
break;
case S_AND:
case S_SUB:
t1 = 0;
t2 = addr(&e2);
if (more()) {
if ((t2 != S_R8) || (e2.e_addr != A))
++t1;
comma();
t2 = addr(&e2);
}
if (rf==S_SUB && t2!=S_IMMED) {
if (genop(0xCB, op, &e2, 0) || t1)
aerr();
} else {
if (genop(0, op, &e2, 1) || t1)
aerr();
}
break;
case S_ADD:
case S_ADC:
case S_SBC:
t1 = addr(&e1);
t2 = 0;
if (more()) {
comma();
t2 = addr(&e2);
}
if (t2 == 0) {
if (genop(0, op, &e1, 1))
aerr();
break;
}
if ((t1 == S_R8) && (e1.e_addr == A)) {
if (genop(0, op, &e2, 1))
aerr();
break;
}
if ((t1 == S_R16) && (t2 == S_R16)) {
if (rf == S_ADD)
op = 0x09;
if (rf == S_ADC)
op = 0x4A;
if (rf == S_SBC)
op = 0x42;
v1 = e1.e_addr;
v2 = e2.e_addr;
if ((v1 == HL) && (v2 <= SP)) {
if (rf != S_ADD)
outab(0xED);
outab(op | (v2<<4));
break;
}
if (rf != S_ADD) {
aerr();
break;
}
if ((v1 == IX) && (v2 != HL) && (v2 != IY)) {
if (v2 == IX)
v2 = HL;
outab(0xDD);
outab(op | (v2<<4));
break;
}
if ((v1 == IY) && (v2 != HL) && (v2 != IX)) {
if (v2 == IY)
v2 = HL;
outab(0xFD);
outab(op | (v2<<4));
break;
}
}
aerr();
break;
case S_LD:
t1 = addr(&e1);
comma();
t2 = addr(&e2);
if (t1 == S_R8) {
v1 = op | e1.e_addr<<3;
if (genop(0, v1, &e2, 0) == 0)
break;
if (t2 == S_IMMED) {
outab(e1.e_addr<<3 | 0x06);
outrb(&e2,0);
break;
}
}
v1 = e1.e_addr;
v2 = e2.e_addr;
if ((t1 == S_R16) && (t2 == S_IMMED)) {
v1 = gixiy(v1);
outab(0x01|v1<<4);
outrw(&e2, 0);
break;
}
if ((t1 == S_R16) && (t2 == S_INDM)) {
if (gixiy(v1) == HL) {
outab(0x2A);
} else {
outab(0xED);
outab(0x4B | v1<<4);
}
outrw(&e2, 0);
break;
}
if ((t1 == S_INDM) && (t2 == S_R16)) {
if (gixiy(v2) == HL) {
outab(0x22);
} else {
outab(0xED);
outab(0x43 | v2<<4);
}
outrw(&e1, 0);
break;
}
if ((t1 == S_R8) && (v1 == A) && (t2 == S_INDM)) {
outab(0x3A);
outrw(&e2, 0);
break;
}
if ((t1 == S_INDM) && (t2 == S_R8) && (v2 == A)) {
outab(0x32);
outrw(&e1, 0);
break;
}
if ((t2 == S_R8) && (gixiy(t1) == S_IDHL)) {
outab(0x70|v2);
if (t1 != S_IDHL)
outrb(&e1, 0);
break;
}
if ((t2 == S_IMMED) && (gixiy(t1) == S_IDHL)) {
outab(0x36);
if (t1 != S_IDHL)
outrb(&e1, 0);
outrb(&e2, 0);
break;
}
if ((t1 == S_R8X) && (t2 == S_R8) && (v2 == A)) {
outab(0xED);
outab(v1);
break;
}
if ((t1 == S_R8) && (v1 == A) && (t2 == S_R8X)) {
outab(0xED);
outab(v2|0x10);
break;
}
if ((t1 == S_R16) && (v1 == SP)) {
if ((t2 == S_R16) && (gixiy(v2) == HL)) {
outab(0xF9);
break;
}
}
if ((t1 == S_R8) && (v1 == A)) {
if ((t2 == S_IDBC) || (t2 == S_IDDE)) {
outab(0x0A | (t2-S_INDR)<<4);
break;
}
}
if ((t2 == S_R8) && (v2 == A)) {
if ((t1 == S_IDBC) || (t1 == S_IDDE)) {
outab(0x02 | (t1-S_INDR)<<4);
break;
}
}
aerr();
break;
case S_EX:
t1 = addr(&e1);
comma();
t2 = addr(&e2);
if (t2 == S_R16) {
v1 = e1.e_addr;
v2 = e2.e_addr;
if ((t1 == S_IDSP) && (v1 == 0)) {
if (gixiy(v2) == HL) {
outab(op);
break;
}
}
if (t1 == S_R16) {
if ((v1 == DE) && (v2 == HL)) {
outab(0xEB);
break;
}
}
}
if ((t1 == S_R16X) && (t2 == S_R16X)) {
outab(0x08);
break;
}
aerr();
break;
case S_IN:
case S_OUT:
if (rf == S_IN) {
t1 = addr(&e1);
comma();
t2 = addr(&e2);
} else {
t2 = addr(&e2);
comma();
t1 = addr(&e1);
}
v1 = e1.e_addr;
v2 = e2.e_addr;
if (t1 == S_R8) {
if ((v1 == A) && (t2 == S_INDM)) {
outab(op);
outab(v2);
break;
}
if (t2 == S_IDC) {
outab(0xED);
outab(((rf == S_IN) ? 0x40 : 0x41) + (v1<<3));
break;
}
}
aerr();
break;
case S_DEC:
case S_INC:
t1 = addr(&e1);
v1 = e1.e_addr;
if (t1 == S_R8) {
outab(op|(v1<<3));
break;
}
if (t1 == S_IDHL) {
outab(op|0x30);
break;
}
if (t1 != gixiy(t1)) {
outab(op|0x30);
outrb(&e1,0);
break;
}
if (t1 == S_R16) {
v1 = gixiy(v1);
if (rf == S_INC) {
outab(0x03|(v1<<4));
break;
}
if (rf == S_DEC) {
outab(0x0B|(v1<<4));
break;
}
}
aerr();
break;
case S_DJNZ:
case S_JR:
if ((v1=admode(CND)) && (rf != S_DJNZ)) {
if ((v1&=0xFF) <= 0x18) {
op += (v1+1)<<3;
} else {
aerr();
}
comma();
}
expr(&e2, 0);
v2 = e2.e_addr - dot->s_addr - 2;
if ((v2 < -128) || (v2 > 127))
aerr();
if (e2.e_base.e_ap != dot->s_area)
rerr();
outab(op);
outab(v2);
break;
case S_CALL:
if (v1=admode(CND)) {
op |= (v1&0xFF)<<3;
comma();
} else {
op = 0xCD;
}
expr(&e1, 0);
outab(op);
outrw(&e1, 0);
break;
case S_JP:
if (v1=admode(CND)) {
op |= (v1&0xFF)<<3;
comma();
expr(&e1, 0);
outab(op);
outrw(&e1, 0);
break;
}
t1 = addr(&e1);
if (t1 == S_USER) {
outab(0xC3);
outrw(&e1, 0);
break;
}
if ((e1.e_addr == 0) && (gixiy(t1) == S_IDHL)) {
outab(0xE9);
break;
}
aerr();
break;
case X_HD64:
++hd64;
break;
case X_INH2:
outab(0xED);
outab(op);
break;
case X_IN:
case X_OUT:
if (rf == X_IN) {
t1 = addr(&e1);
comma();
t2 = addr(&e2);
} else {
t2 = addr(&e2);
comma();
t1 = addr(&e1);
}
if ((t1 == S_R8) && (t2 == S_INDM)) {
outab(0xED);
outab(op | e1.e_addr<<3);
outrb(&e2, 0);
break;
}
aerr();
break;
case X_MLT:
t1 = addr(&e1);
if ((t1 == S_R16) && ((v1 = e1.e_addr) <= SP)) {
outab(0xED);
outab(op | v1<<4);
break;
}
aerr();
break;
case X_TST:
t1 = addr(&e1);
if (t1 == S_R8) {
outab(0xED);
outab(op | e1.e_addr<<3);
break;
}
if (t1 == S_IDHL) {
outab(0xED);
outab(0x34);
break;
}
if (t1 == S_IMMED) {
outab(0xED);
outab(0x64);
outrb(&e1, 0);
break;
}
aerr();
break;
case X_TSTIO:
t1 = addr(&e1);
if (t1 == S_IMMED) {
outab(0xED);
outab(op);